#include "ModuleMixer.h"

namespace modx {

	ModuleMixer::ModuleMixer(unsigned long sampleRate, int channels) {
		m_lSampRate = sampleRate;
		m_iChannels = channels;		
		if(!sampleRate || !channels) {
			return;
		}
		
	}
	ModuleMixer::~ModuleMixer() {
		freeChannels();
	}
	
	unsigned long ModuleMixer::out16(short in[], unsigned long nSamples) {
		unsigned long i;
		int nch;
		
		if(nSamples == 0) {
			return 0;
		}
			
		memset(in, 0, sizeof(short) * nSamples);
		for(nch = 0; nch < m_iChannels; nch++) {
			MixChn *chn = m_vChn.at(nch);
			
			if(chn->data != 0) {
					
				for(i = 0; i < nSamples; i++) {
					in[i] += chn->data[chn->pos >> RESAMP_SHIFT] * chn->vol;
					chn->pos += chn->inc;
					
					if(chn->loopLength) {
						if(chn->pos >= (chn->loopStart + chn->loopLength)) {
								chn->pos -= chn->loopLength;
						}
					}
					if(chn->pos >= chn->length) {
						chn->data = NULL;
						break;
					}
				}
			}
		}
		return nSamples;
	}
	
	unsigned long ModuleMixer::getSampleRate() {
		return m_lSampRate;
	}
	
	void ModuleMixer::freeChannels() {
		for(int chn = 0; chn < m_iChannels; chn++) {
			try {
				delete m_vChn.at(chn);
			} catch(std::out_of_range e) {
				continue;
			}
		}	
		m_vChn.clear();
	}
	int ModuleMixer::getNumChannels() {
		return m_iChannels;
	}
	
	void ModuleMixer::setNumChannels(int nCh) {
		freeChannels();
		
		m_iChannels = nCh;
		MixChn* cur;
		for(int chn = 0; chn < m_iChannels; chn++) {
			try {
				cur = new MixChn;
				cur->data = NULL;
				cur->pos = 0;
				cur->inc = 0;
				cur->vol = 0;
				cur->length = 0;
				cur->loopLength = 0;
				m_vChn.push_back(cur);
			} catch(std::bad_alloc e) {
				m_iChannels = chn;
				break;
			}
		}		
	}
	
	MixChn* ModuleMixer::getChannel(int cx) {
		try {
			return m_vChn.at(cx);
		} catch(std::out_of_range e) {
			return NULL;
		}
	}
}